use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use sqlx::FromRow;
use uuid::Uuid;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CrawlerConfig {
    pub platform: String,
    pub crawler_type: String,
    pub login_type: String,
    pub save_data_option: String,
    pub keywords: String,
    pub crawl_count: i32,
    pub start_page: i32,
    pub concurrency: i32,
    pub enable_comments: bool,
    pub enable_sub_comments: bool,
    pub enable_media: bool,
    pub enable_proxy: bool,
}

impl Default for CrawlerConfig {
    fn default() -> Self {
        Self {
            platform: "xhs".to_string(),
            crawler_type: "search".to_string(),
            login_type: "qrcode".to_string(),
            save_data_option: "sqlite".to_string(),
            keywords: "游戏,pan.quark.cn,资源分享".to_string(),
            crawl_count: 200,
            start_page: 1,
            concurrency: 3,
            enable_comments: true,
            enable_sub_comments: false,
            enable_media: false,
            enable_proxy: false,
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CrawlerStatus {
    pub is_running: bool,
    pub is_paused: bool,
    pub current_task: String,
    pub progress: f64,
    pub crawled_count: i32,
    pub success_count: i32,
    pub failed_count: i32,
    pub skipped_count: i32,
    pub speed: f64,
    pub elapsed_time: String,
    pub estimated_time: String,
}

impl Default for CrawlerStatus {
    fn default() -> Self {
        Self {
            is_running: false,
            is_paused: false,
            current_task: String::new(),
            progress: 0.0,
            crawled_count: 0,
            success_count: 0,
            failed_count: 0,
            skipped_count: 0,
            speed: 0.0,
            elapsed_time: "00:00".to_string(),
            estimated_time: "00:00".to_string(),
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
pub struct CrawledData {
    pub id: String,
    pub platform: String,
    pub data_type: String,
    pub title: String,
    pub content: Option<String>,
    pub author: String,
    pub author_id: String,
    pub url: String,
    pub like_count: i32,
    pub comment_count: i32,
    pub share_count: i32,
    pub view_count: i32,
    pub created_at: DateTime<Utc>,
    pub crawled_at: DateTime<Utc>,
    pub keywords: String,
}

impl CrawledData {
    pub fn new(platform: &str, data_type: &str) -> Self {
        Self {
            id: Uuid::new_v4().to_string(),
            platform: platform.to_string(),
            data_type: data_type.to_string(),
            title: String::new(),
            content: None,
            author: String::new(),
            author_id: String::new(),
            url: String::new(),
            like_count: 0,
            comment_count: 0,
            share_count: 0,
            view_count: 0,
            created_at: Utc::now(),
            crawled_at: Utc::now(),
            keywords: String::new(),
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LogEntry {
    pub time: String,
    pub level: String,
    pub message: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DataOverview {
    pub platform: String,
    pub platform_icon: String,
    pub data_type: String,
    pub total_count: i32,
    pub today_count: i32,
    pub last_update: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PlatformStats {
    pub platform: String,
    pub icon: String,
    pub total_tasks: i32,
    pub success_tasks: i32,
    pub failed_tasks: i32,
    pub total_data: i32,
    pub avg_speed: f64,
    pub success_rate: f64,
    pub last_update: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SystemInfo {
    pub os: String,
    pub arch: String,
    pub version: String,
    pub memory_usage: String,
    pub cpu_usage: f64,
    pub disk_usage: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ExportOptions {
    pub format: String,
    pub date_range: Option<(DateTime<Utc>, DateTime<Utc>)>,
    pub fields: Vec<String>,
    pub platforms: Vec<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
pub struct Task {
    pub id: String,
    pub name: String,
    pub platform: String,
    pub task_type: String,
    pub keywords: String,
    pub status: String,
    pub progress: f64,
    pub total_count: i32,
    pub success_count: i32,
    pub failed_count: i32,
    pub created_at: DateTime<Utc>,
    pub started_at: Option<DateTime<Utc>>,
    pub completed_at: Option<DateTime<Utc>>,
    pub error_message: Option<String>,
    pub config: Option<String>, // 存储为JSON字符串
}

impl Task {
    pub fn new(name: &str, platform: &str, task_type: &str, keywords: &str, config: &CrawlerConfig) -> Self {
        let config_json = serde_json::to_string(config).unwrap_or_default();
        
        Self {
            id: Uuid::new_v4().to_string(),
            name: name.to_string(),
            platform: platform.to_string(),
            task_type: task_type.to_string(),
            keywords: keywords.to_string(),
            status: "pending".to_string(),
            progress: 0.0,
            total_count: 0,
            success_count: 0,
            failed_count: 0,
            created_at: Utc::now(),
            started_at: None,
            completed_at: None,
            error_message: None,
            config: Some(config_json),
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
pub struct TaskLog {
    pub id: String,
    pub task_id: String,
    pub level: String,
    pub message: String,
    pub created_at: DateTime<Utc>,
}

impl TaskLog {
    pub fn new(task_id: &str, level: &str, message: &str) -> Self {
        Self {
            id: Uuid::new_v4().to_string(),
            task_id: task_id.to_string(),
            level: level.to_string(),
            message: message.to_string(),
            created_at: Utc::now(),
        }
    }
}
